package me.zhengjie.kwService.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.extern.slf4j.Slf4j;
import me.zhengjie.exception.ParameterException;
import me.zhengjie.kwService.ExamStudentService;
import me.zhengjie.kwService.StudentService;
import me.zhengjie.mapper.ExamRoomMapper;
import me.zhengjie.mapper.ExamStudentMapper;
import me.zhengjie.mapper.StudentMapper;
import me.zhengjie.pojo.entity.ExamRoom;
import me.zhengjie.pojo.entity.ExamStudent;
import me.zhengjie.pojo.entity.Student;
import me.zhengjie.pojo.export.ExamStudentExport;
import me.zhengjie.pojo.export.ExaminationResultExport;
import me.zhengjie.util.AssertUtils;
import me.zhengjie.util.BaseResponse;
import me.zhengjie.util.ruoyiexcel.ExcelUtil;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @author Long
 * @date 2021/6/28 17:31
 */
@Service
@Slf4j
public class ExamStudentServiceImpl extends ServiceImpl<ExamStudentMapper, ExamStudent> implements ExamStudentService {
    @Autowired
    private ExamStudentMapper examStudentMapper;
    @Autowired
    private ExamRoomMapper examRoomMapper;
    @Autowired
    private StudentMapper studentMapper;
    @Autowired
    private StudentService studentService;

    @Override
    public List<ExamStudent> selectList() {
        return examStudentMapper.selectList(null);
    }

    @Override
    public BaseResponse export(HttpServletResponse response, List<ExamStudent> examStudents) {
        /**如果选中了数据导出，那么查询出对应的考场id的考场名添加到导出模板中导出*/
        LinkedList<ExamStudentExport> StudentExportList = new LinkedList<>();
        if (examStudents.size() != 0 && examStudents != null) {
            for (ExamStudent examStudent : examStudents) {
                ExamStudentExport studentExport = new ExamStudentExport();
                BeanUtils.copyProperties(examStudent, studentExport);
                if (examStudent.getExamRoomId() != null) {
                    ExamRoom examRoom = examRoomMapper.selectById(examStudent.getExamRoomId());
                    if (examRoom != null && StringUtils.isNotBlank(examRoom.getNameCn())) {
                        studentExport.setExamRoomNameCn(examRoom.getNameCn());
                    }
                }
                StudentExportList.add(studentExport);
            }
        } else {
            /**如果没选中数据导出，那么默认导出全部数据*/
            List<ExamStudent> list = examStudentMapper.selectList(null);
            for (ExamStudent examStudent : list) {
                ExamStudentExport studentExport = new ExamStudentExport();
                BeanUtils.copyProperties(examStudent, studentExport);
                if (examStudent.getExamRoomId() != null) {
                    ExamRoom examRoom = examRoomMapper.selectById(examStudent.getExamRoomId());
                    studentExport.setExamRoomNameCn(examRoom.getNameCn());
                }
                StudentExportList.add(studentExport);
            }
        }
        if (StudentExportList.size() > 0) {
            ExcelUtil<ExamStudentExport> excelUtil = new ExcelUtil<>(ExamStudentExport.class);
            try {
                /*excelUtil.exportExcel(StudentExportList, "考生安排信息");*/
                excelUtil.exportExcel(response, StudentExportList, "考生安排信息");
                return BaseResponse.ok("导出成功");
            } catch (Exception e) {
                e.printStackTrace();
                return BaseResponse.failed("导出失败：" + e.getMessage());
            }
        }
        return BaseResponse.ok("无数据可导出");
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void saveImportList(List<ExamStudentExport> examStudentExports, Integer examId) {
        HashMap<Integer, Integer> map = new HashMap<>();
        /*统计本地导入的考生*/
        Set<String> idCards = examStudentExports.stream().map(ExamStudentExport::getIdCard).collect(Collectors.toSet());
        /*处理导入的数据*/
        for (ExamStudentExport studentExport : examStudentExports) {
            /*校验参数不可为空*/
            AssertUtils.isNotNull(studentExport.getExaminee(), "准考证、身份证、考生姓名、手机号必填");
            AssertUtils.isNotNull(studentExport.getIdCard(), "准考证、身份证、考生姓名、手机号必填");
            AssertUtils.isNotNull(studentExport.getNameCn(), "准考证、身份证、考生姓名、手机号必填");
            AssertUtils.isNotNull(studentExport.getPhone(), "准考证、身份证、考生姓名、手机号必填");
            AssertUtils.isMobile(studentExport.getPhone(),studentExport.getNameCn()+"的手机号格式不正确");
            AssertUtils.isIdCard(studentExport.getIdCard(),studentExport.getNameCn()+"的身份证号格式不正确");

            ExamStudent examStudent = new ExamStudent();
            BeanUtils.copyProperties(studentExport, examStudent);
            examStudent.setExamId(examId);
            /*取出导入的考场名去查询出对应的考场id存入考场考生信息表*/
            if (StringUtils.isNotBlank(studentExport.getExamRoomNameCn())) {
                QueryWrapper<ExamRoom> examRoomWrapper = new QueryWrapper<>();
                examRoomWrapper.eq("name_cn", studentExport.getExamRoomNameCn());
                ExamRoom examRoom = examRoomMapper.selectOne(examRoomWrapper);
                AssertUtils.isNotNull(examRoom, "不存在这个考场：" + studentExport.getExamRoomNameCn());
                /*校验考生座位号不重复*/
                assertSeatIsNotRepeat(examStudentMapper, examStudentExports, examId, idCards, studentExport, examRoom);
                /*查询出此考场中没有在此次导入列表中的已有的考生*/
                QueryWrapper<ExamStudent> wrapper = new QueryWrapper<>();
                wrapper.eq("exam_id", examId)
                        .eq("exam_room_id", examRoom.getId())
                        .notIn(idCards != null && !idCards.isEmpty(), "id_card", idCards);
                map.put(examRoom.getId(), examStudentMapper.selectCount(wrapper));
                log.info("考场：{},已有考生：{}", examRoom.getRoomName(), map.get(examRoom.getId()));
                /*统计这个考场名有多少个考生添加进来*/
                long count = examStudentExports.stream().filter(examStudentExport -> Objects.equals(examStudentExport.getExamRoomNameCn(), studentExport.getExamRoomNameCn())).count();
                /*获取次考场的*/
                Integer studentCount = map.get(examRoom.getId());
                examStudent.setExamRoomId(examRoom.getId());
                if (count > examRoom.getSeatNumber())
                    throw new ParameterException("导入" + studentExport.getExamRoomNameCn() + "考场的考生超过了此考场可容纳数量");
                else if (studentCount != null && count + studentCount > examRoom.getSeatNumber())
                    throw new ParameterException("导入" + studentExport.getExamRoomNameCn() + "考场的考生超过了此考场可容纳数量");

            }

            /*获取导入的身份证查询考生信息是否存在如果不存在则插入,返回学生id，存入*/
            QueryWrapper<Student> studentWrapper = new QueryWrapper<>();
            studentWrapper.eq(StringUtils.isNotBlank(studentExport.getIdCard()), "id_card", studentExport.getIdCard());
            Student selectStudent = studentMapper.selectOne(studentWrapper);
            if (selectStudent == null) {
                Student student = new Student();
                BeanUtils.copyProperties(studentExport, student);
                studentMapper.insert(student);
                examStudent.setStudentId(student.getId());
            } else {
                examStudent.setStudentId(selectStudent.getId());
            }
            QueryWrapper<ExamStudent> wrapper = new QueryWrapper<>();
            wrapper.eq("id_card", examStudent.getIdCard())
                    .eq("exam_id", examStudent.getExamId());
            saveOrUpdate(examStudent, wrapper);
        }

    }

    /**
     * 校验同场考试同场考场座位号是否重复
     *
     * @param examStudentMapper  考生安排Mapper
     * @param examStudentExports 导入的考生安排文件
     * @param examId             考试ID
     * @param idCards            导入的考生身份证集合
     * @param studentExport      本次循环的导入考生
     * @param examRoom           本次循环的考生的考场
     */
    private void assertSeatIsNotRepeat(ExamStudentMapper examStudentMapper, List<ExamStudentExport> examStudentExports, Integer examId, Set<String> idCards, ExamStudentExport studentExport, ExamRoom examRoom) {
        /*如果填写了考生的座位号校验考生座位号是否重复*/
        if (StringUtils.isBlank(studentExport.getSeat())) return;
        /*统计是否有同一考场相同座位号的考生*/
        long theSameSeatCount = examStudentExports.stream()
                .filter(examStudentExport -> StringUtils.isNotBlank(examStudentExport.getExamRoomNameCn()))
                .filter(examStudentExport -> StringUtils.isNotBlank(examStudentExport.getSeat()))
                .filter(examStudentExport -> Objects.equals(examStudentExport.getExamRoomNameCn(), studentExport.getExamRoomNameCn()))
                .filter(examStudentExport -> Objects.equals(examStudentExport.getSeat(), studentExport.getSeat())).count();
        if (theSameSeatCount > 1)
            throw new ParameterException(studentExport.getExamRoomNameCn() + "考场的" + studentExport.getSeat() + "座位号有多个考生");

        /*查询此考生的座位号是否已经有同学入座了*/
        QueryWrapper<ExamStudent> examStudentQueryWrapper = new QueryWrapper<>();
        examStudentQueryWrapper.eq("exam_id", examId)
                .eq("exam_room_id", examRoom.getId())
                .eq("seat", studentExport.getSeat())
                .notIn("id_card", idCards);
        List<ExamStudent> students = examStudentMapper.selectList(examStudentQueryWrapper);
        if (students.size() > 0)
            throw new ParameterException(studentExport.getExamRoomNameCn() + "考场的" + studentExport.getSeat() + "座位号已经有同学入座了");
    }

    @Override
    public BaseResponse exportExaminationResult(HttpServletResponse response, List<ExamStudent> examStudents) {
        /*传入的考生信息不为空，则导出传入的考生出成绩*/
        LinkedList<ExaminationResultExport> list = new LinkedList<>();
        if (examStudents != null && examStudents.size() > 0) {
            for (ExamStudent examStudent : examStudents) {
                ExaminationResultExport resultExport = new ExaminationResultExport();
                BeanUtils.copyProperties(examStudent, resultExport);
                list.add(resultExport);
            }

        } else {
            /*传入的考生信息为空，则导出全部考生成绩*/
            List<ExamStudent> selectList = examStudentMapper.selectList(null);
            for (ExamStudent examStudent : selectList) {
                ExaminationResultExport resultExport = new ExaminationResultExport();
                BeanUtils.copyProperties(examStudent, resultExport);
                list.add(resultExport);
            }
        }

        if (list.size() > 0) {
            ExcelUtil<ExaminationResultExport> excelUtil = new ExcelUtil<>(ExaminationResultExport.class);
            try {
                excelUtil.exportExcel(response, list, "考生成绩");
                return BaseResponse.ok();
            } catch (IOException e) {
                e.printStackTrace();
                return BaseResponse.failed("导出失败：" + e.getMessage());
            }
        }
        return BaseResponse.failed("无数据可导出");
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void saveImportExaminationResult(List<ExaminationResultExport> resultExportList) {
        for (ExaminationResultExport resultExport : resultExportList) {
            QueryWrapper<ExamStudent> wrapper = new QueryWrapper<>();
            wrapper.eq(StringUtils.isNotBlank(resultExport.getIdCard()), "id_card", resultExport.getIdCard())
                    .eq(StringUtils.isNotBlank(resultExport.getNameCn()), "name_cn", resultExport.getNameCn());
            ExamStudent examStudent = examStudentMapper.selectOne(wrapper);
            if (examStudent == null) {
                ExamStudent student = new ExamStudent();
                BeanUtils.copyProperties(resultExport, student);
                examStudentMapper.insert(student);
            } else {
                examStudent.setScore(resultExport.getScore());
                updateById(examStudent);
            }
        }
    }

}
